import csv
import io

MAX_TAPE_LENGTH = 4096  # 纸带的最大长度限制

def parse_instructions(input_string):
    """
    解析五元组指令，并返回结构化的指令元组列表。
    如果某一行使用冒号分隔，则识别为特殊配置：带、初、空。
    """
    input_string = input_string.replace(',', ' ').replace('|', ' ')
    f = io.StringIO(input_string)

    reader = csv.reader(f, skipinitialspace=True, quotechar="'", delimiter=' ')
    
    instructions = []
    config = {"tape": "", "state": "", "blank_symbol": " "}
    
    for row in reader:
        # 过滤掉空字符串
        row = [elem for elem in row if elem]
        if len(row) == 0:
            continue

        if len(row) == 1 and ':' in row[0]:
            # 处理冒号分隔的配置项
            key, value = map(str.strip, row[0].split(':', 1))
            if key in ["带", "tape"]:
                config["tape"] = value
            elif key in ["初", "state"]:
                config["state"] = value
            elif key in ["空", "blank"]:
                config["blank_symbol"] = value
            continue
        
        if len(row) != 5:
            raise ValueError("输入的指令数量不符合五元组格式。")

        instructions.append(tuple(row))  # 直接使用元组存储

    return instructions, config

class TuringMachine:
    def __init__(self, config):
        self.raw_instructions = config['raw_instructions']
        instructions, parsed_config = parse_instructions(self.raw_instructions)
        
        # 构建指令集
        self.instructions = {
            (state, symbol): (next_state, write, direction) 
            for state, symbol, next_state, write, direction in instructions
        }

        # 初始化纸带和配置
        self.tape = list(config.get("tape", parsed_config.get("tape", "")))
        self.error_msg = None  # 初始化错误消息属性
        if len(self.tape) > MAX_TAPE_LENGTH:
            self.error_msg = f"纸带长度超过最大限制 {MAX_TAPE_LENGTH} 个字符。"

        self.head_position = config.get("head_position", 0)
        self.current_state = config["state"] if config.get("state") else parsed_config.get("state", "")
        self.blank_symbol = config["blank_symbol"] if config.get("blank_symbol") else parsed_config.get("blank_symbol", " ")

        # 新增 cycles 字段初始化
        self.cycles = config.get("cycles", 0)

    def step(self):
        if self.error_msg:
            print(f"错误: {self.error_msg}")
            return False

        # self.print_tape_with_head()
        if len(self.tape) > MAX_TAPE_LENGTH:
            self.error_msg = f"纸带长度超过最大限制 {MAX_TAPE_LENGTH} 个字符。"
            return False
        
        if self.head_position < 0 or self.head_position >= len(self.tape):
            current_symbol = self.blank_symbol
        else:
            current_symbol = self.tape[self.head_position]

        key = (self.current_state, current_symbol)
        if key not in self.instructions:
            self.error_msg = f"进入可接受状态 [{self.current_state}] '{current_symbol}'"
            print(f"进入可接受状态 [{self.current_state}] '{current_symbol}'")
            return False

        next_state, write_symbol, move_direction = self.instructions[key]
        print(f"\t==> [{next_state}] '{write_symbol}' {move_direction}")
        
        if self.head_position < len(self.tape):
            self.tape[self.head_position] = write_symbol
        else:
            self.tape.append(write_symbol)

        if move_direction == 'R':
            self.head_position += 1
            if self.head_position >= len(self.tape):
                if len(self.tape) >= MAX_TAPE_LENGTH:
                    self.error_msg = f"纸带长度超过最大限制 {MAX_TAPE_LENGTH} 个字符。"
                    return False
                self.tape.append(self.blank_symbol)
        elif move_direction == 'L':
            self.head_position -= 1
            if self.head_position < 0:
                return False
        elif move_direction == 'H':
            pass

        self.current_state = next_state

        # 每次 step 后增加 cycles 计数
        self.cycles += 1
        return True

    def print_tape_with_head(self):
        print(f"[{self.current_state}] +{self.cycles}")
        tape_str = ''.join(self.tape)
        head_indicator = ' ' * self.head_position + '^'
        print(tape_str)
        print(head_indicator)  # , f"({self.head_position})"

    def run(self, max_steps=1000):
        steps = 0
        while steps < max_steps:
            if self.error_msg:
                print(f"错误: {self.error_msg}")
                break
            if not self.step():
                break
            steps += 1
        else:
            print("达到最大步数，停止执行。")
            self.print_tape_with_head()

    def desc(self):
        """返回图灵机的当前状态描述作为字典。"""
        return {
            "raw_instructions": self.raw_instructions,
            "tape": ''.join(self.tape),  # 将纸带转回字符串形式
            "state": self.current_state,
            "head_position": self.head_position,
            "blank_symbol": self.blank_symbol,
            "cycles": self.cycles,  # 包含 cycles 字段
            "error_msg": self.error_msg  # 包含错误消息
        }
